﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Driver;
using Lynn.Infastructure.Repository.Dapper;
using Lynn.Infastructure.Repository.EFCore;
using Lynn.Infastructure.Repository.MongoDB;
using System;

namespace Lynn.Infastructure.Repository
{
    public static class RepositoryService
    {
        /// <summary>
        /// 数据库
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="database">链接</param>
        /// <param name="showSql">控制台输出Sql</param>
        /// <param name="baseType">数据库类型</param>
        /// <param name="pollSize">连接池大小，注意要小于数据库连接池的Max_Pool_Size</param>
        /// <returns></returns>
        public static IServiceCollection AddEFCore<TContext>(this IServiceCollection services, string database, bool showSql = false, DataBaseType baseType = DataBaseType.MySql, int pollSize = 64) where TContext : EFCoreBaseContext
        {
            //数据库配置
            services.AddDbContextPool<TContext>(c =>
            {
                switch (baseType)
                {
                    default: c.UseSqlServer(database); break;
                    case DataBaseType.MySql: c.UseMySql(database, ServerVersion.AutoDetect(database)); break;
                    case DataBaseType.SqlLite: c.UseSqlite(database); break;
                }
                if (showSql)
                {
                    c.UseLoggerFactory(LoggerFactory.Create(builder => { builder.AddConsole(); }));
                }
            }, pollSize);
            services.AddAppService<TContext>(AppServiceTargets.Scoped);
            return services;
        }
        /// <summary>
        /// 数据库迁移
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static void Migrate<TContext>(this IServiceCollection services) where TContext : EFCoreBaseContext
        {
            var context = services.BuildServiceProvider().GetService<TContext>();
            context.Database.EnsureCreated();
            context.Database.Migrate();
        }
        /// <summary>
        /// MongoDB配置
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="connectionString"></param>
        /// <param name="databaseName"></param>
        /// <returns></returns>
        public static IServiceCollection AddMongoDB<TContext>(this IServiceCollection services, string ConnectionString, string DatabaseName) where TContext : MongoBaseContext, new()
        {

            //数据库配置
            services.AddSingleton(p =>
            {
                var context = new TContext();
                context.Client = new MongoClient(ConnectionString);
                context.ConnectionString = ConnectionString;
                context.DatabaseName = DatabaseName;
                ConventionRegistry.Register("default",
                new ConventionPack
                {
                 new IgnoreIfNullConvention(true),
                 new IgnoreExtraElementsConvention(true)
                },
                c => true);
                return context;
            });
            services.AddAppService<TContext>(AppServiceTargets.Scoped);
            return services;
        }

        public static IServiceCollection AddDapper<TContext>(this IServiceCollection services, string database, DataBaseType baseType = DataBaseType.SqlServer) where TContext : DapperBaseContext, new()
        {
            services.TryAddScoped(p =>
            {
                var context = new TContext();
                context.Init(database, baseType);
                return context;
            });
            services.AddAppService<TContext>(AppServiceTargets.Scoped);
            return services;
        }
    }
}
